Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C#: Models for higher order methods. #17742

Merged
merged 7 commits into from
Nov 7, 2024

Conversation

michaelnebel
Copy link
Contributor

@michaelnebel michaelnebel commented Oct 11, 2024

In this PR we added support for read/store steps for delegate calls (where the delegate being called is parameter of a callable) for C#.
The read and store steps for delegate calls and delegate returns are basically "dead ends" and are only relevant for content dataflow related to model generation.

@github-actions github-actions bot added the C# label Oct 11, 2024
@michaelnebel michaelnebel force-pushed the csharp/higherordermodels branch from f25e44b to 21a0f76 Compare October 24, 2024 08:48
@github-actions github-actions bot added the Java label Oct 24, 2024
@michaelnebel michaelnebel force-pushed the csharp/higherordermodels branch 4 times, most recently from cb0b639 to eb1c4e9 Compare October 29, 2024 08:27
@michaelnebel michaelnebel added the no-change-note-required This PR does not need a change note label Oct 29, 2024
@michaelnebel michaelnebel marked this pull request as ready for review October 29, 2024 09:31
@michaelnebel michaelnebel requested review from a team as code owners October 29, 2024 09:31
@michaelnebel michaelnebel requested a review from hvitved October 29, 2024 09:32
Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. Some comments, mainly related to CFG splitting.

TCapturedVariableContent(VariableCapture::CapturedVariable v)
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TDelegateCallArgumentContent(int i) {
i = [0 .. max(int j | j = any(DelegateCall dc).getNumberOfArguments())]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: max(any(DelegateCall dc).getNumberOfArguments()) - 1.

* If there is a delegate call f(x), then we store "x" on "f"
* using a delegate argument content set.
*/
private predicate storeStepDelegateCall(Node node1, ContentSet c, Node node2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation does not properly take CFG splitting into account. I think the following works:

private predicate storeStepDelegateCall(ExplicitArgumentNode node1, ContentSet c, Node node2) {
  exists(ExplicitDelegateLikeDataFlowCall call, int i |
    node1.argumentOf(call, TPositionalArgumentPosition(i)) and
    lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
    c.isDelegateCallArgument(i)
  )
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, thx!
Could you elaborate a bit on, which cases are now covered that wasn't covered before?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old implementation had the issue that it could potentially mix CFG nodes belonging to different CFG splits. Moreover, using DelegateLikeCall instead of just DelegateCall means that function pointers are also taken into account.

* If there is a delegate call f(x), then we read the return of the delegate
* call.
*/
private predicate readStepDelegateCall(Node node1, ContentSet c, Node node2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, because of CFG splitting:

private predicate readStepDelegateCall(Node node1, ContentSet c, OutNode node2) {
  exists(ExplicitDelegateLikeDataFlowCall call |
    lambdaCall(call, _, node1) and
    node2.getCall(TNormalReturnKind()) = call and
    c.isDelegateCallReturn()
  )
}

// neutral=Models;HigherOrderParameters;Map;(System.Func<System.Object,System.Object>,System.Object);summary;df-generated
// contentbased-summary=Models;HigherOrderParameters;false;Map;(System.Func<System.Object,System.Object>,System.Object);;Argument[1];Argument[0].Parameter[0];value;dfc-generated
// contentbased-summary=Models;HigherOrderParameters;false;Map;(System.Func<System.Object,System.Object>,System.Object);;Argument[0].ReturnValue;ReturnValue;value;dfc-generated
public object Map(Func<object, object> f, object o)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Apply would be a more appropriate name.

// neutral=Models;HigherOrderParameters;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);summary;df-generated
// contentbased-summary=Models;HigherOrderParameters;false;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);;Argument[0];Argument[1].Parameter[1];value;dfc-generated
// contentbased-summary=Models;HigherOrderParameters;false;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);;Argument[1].ReturnValue;ReturnValue;value;dfc-generated
public object Map2(object o, Func<object, object, object> f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

}

/**
* Models as Data currently doesn't support callback logic in fields.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's true: For example, I would expect something like this to work just fine:

input = Argument[0].Field[Foo].ReturnValue
output = ReturnValue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that but it didn't work. Furthermore, if Foo is a synthetic field some of the data flow consistency tests start failing. Due to time constraints (and since wasn't that many summaries), I just decided to remove the problematic summaries from the output.
In any case, I will change the wording.

@michaelnebel michaelnebel force-pushed the csharp/higherordermodels branch from eb1c4e9 to e9c9519 Compare November 6, 2024 15:29
Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just one last thing.

@@ -1149,7 +1149,7 @@ private module Cached {
} or
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TDelegateCallArgumentContent(int i) {
i = [0 .. max(int j | j = any(DelegateCall dc).getNumberOfArguments())]
i = [0 .. max(any(DelegateCall dc).getNumberOfArguments())]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still missing the - 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, you are right! Thank you for paying close attention!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we also want to consider DelegateLikeCall instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes.

@michaelnebel michaelnebel merged commit fc8d8bb into github:main Nov 7, 2024
53 of 54 checks passed
@michaelnebel michaelnebel deleted the csharp/higherordermodels branch November 7, 2024 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C# Java no-change-note-required This PR does not need a change note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants